function DayDetailDialog(dom) {
    this._dom = dom;
    this._dayModel = null;
    this._dayDomPosition = null;
    this._lastUsedLocations = null;

    this._activityCheckBoxes = dom.find("input[name='day_detail_activity']");
    this._addLocationLink = $('#add-location');
    this._locationItemTemplate = $('.location-item-template').removeClass('location-item-template').remove();
    this._locationItemViews = [];
    this._errorElement = $('#day_detail_errors');
    this._locationItemsContainer = $('#day_detail_location');
    this._originalTravelSteps = [];
}

DayDetailDialog.prototype = {
    createDialog: function() {
        this._dom.dialog({
            autoOpen: false,
            bgiframe: true,
            modal: true,
            draggable: false,
            dialogClass: 'day-detail-dialog',
            width: '500px',
            beforeclose: function() {
                pwc.hideAllAutocompleteList();
                // Date Picker is not used in new feature.
                //pwc.hideDatePicker();
            }
        });
        
        var me = this;
        this._createDialogTitle();
        me._bindEvents();

        $("#activity_legends label").click(function(e) {
            e.preventDefault();
            if ($("#activity_legends .active", me._dom).size() < 2 || ($(this).hasClass("active"))) {
                me._setLegend(this);
            }
        });
    },

    _setLegend: function(element) {
        $(element).toggleClass("active");
    },

    resetDialog: function() {
        CalendarZIndexManager.adjustModelDialogOverlayZIndex();
        this._showAddLocationLink();
        this._resetLocationUI();
        this.clearErrors();
    },

    showDialog: function(dayModel, lastUsedLocations, position) {
        this._dayModel = dayModel;
        this._dayDomPosition = position;
        this._lastUsedLocations = lastUsedLocations;

        this.resetDialog();
        this._updateDialogTitle(dayModel);

        this._updateUI(dayModel);

        this._openDialog();
        this._blurLocationElements();

        this._setDialogPositionAndOpcacity();
    },

    closeDialog: function() {
        this._dom.dialog('close');
    },
    
    _openDialog: function() {
        this._dom.dialog('open');
    },
    
    _blurLocationElements: function(){
         this._locationItemViews.foreach(function(locationItemView){
            locationItemView.blurLocationElement();
        });
    },

    _createDialogTitle: function() {
        var day_title = '<input type="text" id="day_detail_date" class="inp-t1 day-text" readonly="readonly" value="" />';
        var detail_done = this._dom.find('#day_detail_done').clone();
        detail_done.find('#day_detail_apply').attr('id', 'day_detail_title_apply');
        day_title += detail_done.html();
        this._dom.data('title.dialog', day_title);
        this._applyButton = $('#day_detail_title_apply');
        this._dayTitleElement = $('#day_detail_date');
    },

    _updateDialogTitle: function(dayModel) {
        var day_string = dayModel.getDate().toString(DefaultSetting.dateFormat());
        this._dayTitleElement.val(day_string);
    },

    _setDialogPositionAndOpcacity: function() {
        var dialog = this._dom.parent(".day-detail-dialog");
        var x = this._dayDomPosition[0] - $(window).scrollLeft() - 15;
        var y = this._dayDomPosition[1] - dialog.outerHeight() - 8;

        // Doc3 is the content wrapper in html page.
        var maxX = $("#doc3").offset().left + $("#doc3").width();
        var dialogRight = x + dialog.width();
        var offsetX = dialogRight - maxX >= 0 ? dialogRight - maxX : 0;
        x = x - offsetX;

        var bottomArrow = this._dom.find('.buttom-border');
        bottomArrow.css('left', 48 + offsetX);

        dialog = this._dom.parent(".day-detail-dialog");
        dialog.css('left', x);
        dialog.css('top', y);

        $(".ui-widget-overlay").css('opacity', '0.2');
    },
    
    _resetLocationUI: function() {
        this._locationItemsContainer.html("");
        this._locationItemViews = [];
    },

    _bindEvents: function(){
        var me = this;
        this._addLocationLink.click(function(){
            if (me._locationItemViews.length >= 3){
                return;
            }
            
            var newLocationItemView = me._addEmptyLocationItemView();
            me._resetLocations();
            me._renderLocationView(newLocationItemView);
            me._setDialogPositionAndOpcacity();
        });

        this._applyButton.click(function() {
            me.apply();
        });
    },

    _hideAddLocationLinkWhenNeed: function(){
        if (this._locationItemViews.length >= 3){
            this._addLocationLink.addClass('hidden');
        }
    },

    _showAddLocationLink: function(){
        this._addLocationLink.removeClass('hidden');
    },

    _renderLocationView: function(locationItemView){
        locationItemView.renderTo(this._locationItemsContainer);
        locationItemView.blurLocationElement();
        this._hideAddLocationLinkWhenNeed();
    },

    apply: function() {
        this.applyCallBack();
        this._setDialogPositionAndOpcacity();
    },

    onApply: function(applyCallback) {
        this.applyCallBack = applyCallback;
    },

    showErrors: function(error) {
        this.clearErrors();
        error.errors.foreach(function(aError) {
            var fieldView = $('#' + aError.errorField);
            fieldView.addClass('error');
        });

        this._errorElement.append('<p class="error">' + error.messages().join('<br />') + '</p>');
    },

    clearErrors: function() {
        this._errorElement.find('p.error').remove();
        this._errorElement.find('p.warning').remove();
        this._dom.find('.error').removeClass('error');
    },

    _activityChanged: function(){
        var activities = $("label.active", this._dom);
        var firstActivity = $.trim($(activities[0]).attr('value'));
        var secondActivity = $.trim($(activities[1]).attr('value'));
        return this._dayModel.getActivity() != firstActivity || this._dayModel.getSecondActivity() != secondActivity;
    },


    _travelChanged: function(){
        if(this._locationItemViews.length != this._originalLocationItemValues.length){
            return true;
        }

        var hasChange = false;
        for(var i = 0; i < this._locationItemViews.length; i ++){
            if(!this._locationItemViews[i].isSameAs(this._originalLocationItemValues[i])) {
                hasChange = true;
            }
        }
        return hasChange;
    },

    hasChanged:function() {
        return this._activityChanged() || this._travelChanged();
    },

    toDayDetail: function() {
        var locationText = "";
        var locationViewIndex = 0;
        if(this._currentLocationItemViews.length == 1){
            locationText = this._currentLocationItemViews[0].getLocationText();
            locationViewIndex = this._currentLocationItemViews[0].getIndex();
        }

        var activities = $("label.active", this._dom);
        var dayDetail = new DayDetail(this._dayModel, locationText, $(activities[0]).attr('value'), $(activities[1]).attr('value'));
        dayDetail.locationViewIndex = locationViewIndex;
        return dayDetail;
    },

    toTravel: function() {
        var travel = new Travel();
        var dateError = new Error();
        
        this._originalTravelSteps.foreach(function(travelStep){
            travelStep.toBeDeleted = true;
            travel.addStep(travelStep);
        });

        this._currentLocationItemViews = this._locationItemViews.where(function(locationItemView){
            return locationItemView.getLocationText() != "";
        });
        
        if(this._currentLocationItemViews.length <= 1 && this._originalTravelSteps.length == 0){
            return [null, dateError];
        }

        for(var i=0; i<this._currentLocationItemViews.length - 1; i++) {
            var locationItemView = this._currentLocationItemViews[i];
            var nextLocationItemView = this._currentLocationItemViews[i+1];
            
            var travelStep = new TravelStep({
                'departureLocation': pwc.locationCache.getByFullName(locationItemView.getLocationText()),
                'arrivalLocation': pwc.locationCache.getByFullName(nextLocationItemView.getLocationText()),
                'departureDateTime': locationItemView.getDepartureDateTime(),
                'arrivalDateTime': nextLocationItemView.getArrivalDateTime()
            });

            travelStep.departureViewIndex = locationItemView.getIndex();
            travelStep.arrivalViewIndex = nextLocationItemView.getIndex();

            travel.addStep(travelStep);

            dateError.join(locationItemView.getDepartureDateError());
            dateError.join(nextLocationItemView.getArrivalDateError());
        }

        return [travel, dateError];
    },

    showConflictErrorMessages : function(travelConflictMessages) {
        var me = this;
        this.clearErrors();
        travelConflictMessages.foreach(function(stepConflictMessages) {
            if (!stepConflictMessages) {
                return;
            }

            var errorMessage = i18n("LABEL_TRAVEL_CONFLICTING_WITH") + ' ' + stepConflictMessages.select(function(message) {
                return "\"" + message + "\""
            }).join(',');
            me._errorElement.append('<p class="error">' + errorMessage + '</p>');
        });

        //TODO:: the confilit choices is not desided
//        this.helper.showConflictChoices();
    },

    _updateUI: function(dayModel) {
        this._updateLocationUI(dayModel);
        this._updateActivityUI(dayModel);
    },

    _updateLocationUI: function(dayModel) {
        var me = this;
        var travelSteps = dayModel.getTravelSteps();
        this._originalTravelSteps = travelSteps;
        
        for(var i = 0; i <= travelSteps.length; i++){
            me._addEmptyLocationItemView();
        }
        
        if (!dayModel.hasTravel()){
            me._locationItemViews[0].setLocation(dayModel.getLocation());
        }

        travelSteps.foreach(function(travelStep, i){
            me._updateLocationItemView(i, travelStep.getDepartureLocation(), travelStep.getArrivalLocation(), travelStep.getDepartureDateTime(), travelStep.getArrivalDateTime(), travelStep.getId());
        });

        me._locationItemViews.foreach(function(locationItemView){
            me._renderLocationView(locationItemView);
        });

        me._resetLocations();

        me._originalLocationItemValues = me._locationItemViews.select(function(locationItemView){
            return locationItemView.getValues();
        });
    },

    _resetLocations: function() {
        var me = this;
        this._locationItemViews.foreach(function(locationItemView, i){
            locationItemView.enableArrivalLocation();
            locationItemView.enableDepartureLocation();
            if(i == 0){
                locationItemView.disableArrivalLocation();
            }
            if(i == me._locationItemViews.length - 1) {
                locationItemView.disableDepartureLocation();
            }
        });
    },

    _updateLocationItemView: function(i, departureLocation, arrivalLocation, departureDateTime, arrivalDateTime, id){
        this._locationItemViews[i].setLocation(departureLocation);
        this._locationItemViews[i].setDepartureDateTime(departureDateTime);
        this._locationItemViews[i].setTravelStepId(id);
        this._locationItemViews[i+1].setLocation(arrivalLocation);
        this._locationItemViews[i+1].setArrivalDateTime(arrivalDateTime);
    },

    _addEmptyLocationItemView: function(){
        var locationItemView = new LocationItemView(this._locationItemTemplate.clone(), this._locationItemViews.length);
        locationItemView.setLastUsedLocations(this._lastUsedLocations);
        locationItemView.setArrivalDateTime(new Date(this._dayModel.getDate().setHours(10)));
        locationItemView.setDepartureDateTime(new Date(this._dayModel.getDate().setHours(10)));
        this._locationItemViews.push(locationItemView);
        
        return locationItemView;
    },

    _updateActivityUI: function(dayModel) {
        var firstActivity = dayModel.getActivity();
        var secondActivity = dayModel.getSecondActivity();

        $("label", this._dom).removeClass("active");

        var firstActivityElement = $("label[value='" + firstActivity + "']", this._dom);
        this._setLegend(firstActivityElement);

        var secondActivityElement = $("label[value='" + secondActivity + "']", this._dom);
        this._setLegend(secondActivityElement);
    }
};

function LocationItemView(dom, index){
    this._dom = dom;
    this._index = index;
    this._lastUsedLocations = null;
    this._departureDateTimeContainer = this._dom.find('.departure');
    this._arrivalDateTimeContainer = this._dom.find('.arrival');
    this._locationElement = this._dom.find('.location-text');
    this._locationContainerElement = this._dom.find('.location_container');
    this._departureDateElement = this._dom.find('.departureDate');
    this._departureTimeElement = this._dom.find('.departureTime');
    this._arrivalDateElement = this._dom.find('.arrivalDate');
    this._arrivalTimeElement = this._dom.find('.arrivalTime');
    this._travelStepIdElement = this._dom.find('.travelstep-id');
    this._init(index);
}

LocationItemView.prototype = {
    renderTo: function(container) {
        container.append(this._dom);
    },

    getValues: function(){
        return {
            location: this.getLocationText(),
            arrivalDateTime: this.getArrivalDateTime(),
            departureDateTime: this.getDepartureDateTime()
        }
    },

    isSameAs: function(value){
        return this.getLocationText() == value.location &&
                value.arrivalDateTime.isSame(this.getArrivalDateTime()) &&
                value.departureDateTime.isSame(this.getDepartureDateTime());
    },

    blurLocationElement: function() {
        this._locationElement.blur();
    },

    getLocationText: function(){
        return this._isLocationEmpty() ? "" : $.trim(this._locationElement.val());
    },

    getIndex: function(){
        return this._index;
    },
    
    setLocation: function(location){
        this._locationElement.val(location ? location.fullname : '');
    },

    getDepartureDateError: function(){
        var error = new Error();
        if(this._departureDateElement.val() != '' && !Date.isValid(this._departureDateElement.val())){
            error.addError(i18n("MSG_TRAVEL_DATE_INVALID"), this._departureDateElement.attr('id'));
        }
        return error;
    },

    getArrivalDateError: function(){
        var error = new Error();
        if (this._arrivalDateElement.val() != '' && !Date.isValid(this._arrivalDateElement.val())) {
            error.addError(i18n("MSG_TRAVEL_DATE_INVALID"), this._arrivalDateElement.attr('id'));
        }
        return error;
    },

    setDepartureDateTime: function(dateTime){
        this._departureDateElement.val(dateTime.toString(DefaultSetting.dateFormat()));
        this._departureTimeElement.val(dateTime.toString("HH:00"));
    },

    getDepartureDateTime: function() {
        return this._getDateTime(this._departureDateElement, this._departureTimeElement);
    },

    getArrivalDateTime: function() {
        return this._getDateTime(this._arrivalDateElement, this._arrivalTimeElement);
    },

    _getDateTime: function(dateElement, timeElement){
        return dateElement.val() == "" ? null : Date.parseDateBySettingWith24Time(dateElement.val() + " " + timeElement.val());
    },

    setArrivalDateTime: function(dateTime){
        this._arrivalDateElement.val(dateTime.toString(DefaultSetting.dateFormat()));
        this._arrivalTimeElement.val(dateTime.toString("HH:00"));
    },

    setLastUsedLocations: function(locations){
        this._lastUsedLocations = locations;
    },

    setTravelStepId: function(id){
        this._travelStepIdElement.val(id);
    },
    
    getTravelStepId: function(){
        return this._travelStepIdElement.val();
    },

    disableArrivalLocation: function(){
        this._arrivalDateTimeContainer.addClass('empty');
    },

    enableArrivalLocation: function(){
        this._arrivalDateTimeContainer.removeClass('empty');
    },

    disableDepartureLocation: function(){
        this._departureDateTimeContainer.addClass('empty');
    },

    enableDepartureLocation: function(){
        this._departureDateTimeContainer.removeClass('empty');
    },

    _isLocationEmpty: function(){
        return this._locationElement.hasClass('empty');
    },

    _init: function(index){
        this._setElementIds(index);
        this._bindEvents();
        this._initTimeSelect();
    },

    _setElementIds: function(i){
        this._locationElement.attr('id', "daydetail_location_" + i);
        this._locationContainerElement.attr('id', "daydetail_location_container_" + i);
        this._departureDateElement.attr('id', "daydetail_departure_date_" + i);
        this._departureTimeElement.attr('id', "daydetail_departure_time_" + i);
        this._arrivalDateElement.attr('id', "daydetail_arrival_date_" + i);
        this._arrivalTimeElement.attr('id', "daydetail_arrival_time_" + i);
    },

    _bindEvents: function(){
        var me = this;
        bindDatePickers(this._dom);
        this._locationElement.autoLocation(
            function(){});

        this._locationElement.lastUsedLocationList(
            function(){},
            function(){return me._lastUsedLocations;});
    },

    _initTimeSelect: function(){
        var timeFormat = DefaultSetting.timeFormat();
        var hours = ["01:00", "02:00", "03:00", "04:00", "05:00",
            "06:00", "07:00", "08:00", "09:00", "10:00", "11:00",
            "12:00", "13:00", "14:00", "15:00", "16:00", "17:00",
            "18:00", "19:00", "20:00", "21:00", "22:00", "23:00",
            "00:00"];
        $(".time_select", this._dom).each(function() {
            var time_select = $(this);
            time_select.empty();
            $(hours).each(function() {
                var displayTime = timeFormat === 'HH:mm' ? this : Date.parse(this).toString(timeFormat);
                if (this == "00:00" && timeFormat == "h:mm tt") {
                    displayTime = "12:00 AM";
                }
                time_select.append($('<option value="' + this + '">' + displayTime + '</option>'));
            });
        });
    }
};


